home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-06 | 7.6 KB | 266 lines | [TEXT/MSET] |
- \ 10Dec93 DBH initial version
- \ 12Feb94 DBH added proper disposal of AppleEvent and Reply via AEDisposeDesc at each and
- \ every time we send an AppleEvent. Before, this was causing memory to be consumed and never
- \ freed at each send.
-
- \ It is interesting that, with this scheme at least, it is
- \ not necessary to create and dispose the description record QEdesc at each send.
-
- \ See general comments at the end of this file.
-
-
- \ This AppleEvent class is at the moment geared to sending AEs to
- \ Quick Edit. But it wouldn't be too hard to make it more general.
-
-
- :class AEDesc super{ object }
-
- record
- { longword descriptorType
- handle dataHandle \ first 4 bytes of handle will = MSET after new:
- var dataPtr
- }
-
- :m classinit:
- 'type MSET put: dataPtr \ put QE creator signature in a dataPtr
- ;m
-
- :m new:
- word0 \ room for result
- 'type sign \ typeApplSignature
- addr: dataPtr
- 8 \ dataSize
- ^base \ VAR result -> our record
- call AECreateDesc
- i->l
- 0= not IF ." failed to create AE Desc record" THEN
- ;m
-
- :m release:
- word0 \ room for result
- ^base \ VAR theAEDesc -> our record
- call AEDisposeDesc \ here we actually use AEDisposeDesc to dispose an AEDesc
- i->l
- 0= not IF ." failed to dispose AE Desc record" THEN
- ;m
-
- ;class
-
- AEDesc QEdesc
-
-
-
- variable dummyReply 16 allot
-
- :class AppleEvent super{ object }
-
- record
- { int what
- var mclass
- var when
- var mID
- int modifiers
- var theClass \ will be 'type OPEN or TEXT for now. Could be other things later.
- }
-
- \ :m classinit: \ 12Feb94 DBH necessary??? apparently not
- \ konst kHighLevelEvent put: what ;m
-
- \ Guess what? We have to dispose of our AppleEvent AFTER EACH SEND !
- \ and we must use AEDisposeDesc. This was not immediately obvious to me from IM.
- \ Also, we must dispose of our reply, again using AEDisposeDesc. AEDisposeDesc seems to be
- \ the universal dispoz-all for AE things. The penalty for not doing this is lost heap at every
- \ send.
-
- :m release: \ 12Feb94 DBH
- word0 \ room for result
- ^base call AEDisposeDesc
- i->l
- 0= not IF ." failed to dispose of AppleEvent" THEN
-
- word0 \ room for result
- dummyReply call AEDisposeDesc
- i->l
- 0= not IF ." failed to dispose of Reply" THEN
- ;m
-
- :m new: { theClass theID -- } \ theID MUST be a handle
- word0 \ room for result
- theClass
- theID
- QEdesc \ we are always using this target here
- konst kAutoGenerateReturnID makeint
- 0 \ konst AnyTransactionID \ no call?
- ^base \ VAR result will be our own ivar record , but only using ivars through modifiers
- call AECreateAppleEvent i->l
- 0<> IF " failed to create AppleEvent" cr THEN ;m
-
- \ :m set: ( AEEventClass -- ) \ 12Feb94 DBH incorporated into new:
- \ put: theClass ;m
-
- :m send: ( -- oserr )
- word0 \ room for result
- ^base \ we are sending ourself, of course
- dummyReply
- konst kAEWaitReply \ sendmode, we must wait for reply so we don't clobber the handle
- \ before QE has a chance to deal with it.
- konst kAENormalPriority makeint \ sendPriority
- konst kAEDefaultTimeout \ timeoutinticks see IM-VI 6-94
- 0 \ idleproc
- 0 \ filterproc
- call AESend i->l
- ;m
-
-
- ;class
-
-
- :class QEopen super{ object }
-
- record
- { byte fileNameLength
- 32 bytes fileName
- int volRef#
- var dirID
- var selStart
- var SelEnd
- }
-
- :m put: { ^obj n1 n2 -- } \ file object and desired selection range
- getname: [ ^obj ] ( addr len )
- 32 min dup put: fileNameLength addr: fileName swap cmove \ ala ctl example
-
- getvref: [ ^obj ] put: volRef#
- getdirID: [ ^obj ] put: dirID
- n1 put: selStart
- n2 put: SelEnd ;m
-
- :m length: ( -- n ) \ can't send this message to an ivar!!
- 48 ;m
-
- ;class
-
- \ This class will be used as our sole communication device to QE when sending AEs.
- :class QE super{ object }
-
- AppleEvent QEevent
- QEopen tQEopen
- string+ QEstr
-
- :m new:
- new: QEstr
- new: QEdesc \ note that QEdesc is a public object
- ;m
-
- :m release:
- release: QEstr
- release: QEdesc
- ;m
-
- :m send: ( theClass -- oserr ) \ 12Feb94 DBH must new: and release: for each send!!
- handle: QEstr ( ID ) new: QEevent \ always using QEstr handle as our ID.
- send: QEevent
- clear: QEstr \ 12Feb94 DBH must always clear the string because next action
- \ may be to simply add as when doing a text:
- release: QEevent
- ;m
-
- :m openFile: ( ^obj n1 n2 -- oserr ) \ file object and selection range
- put: tQEopen
- addr: tQEopen length: tQEopen put: QEstr
- 'type OPEN send: self ;m
-
- :m text: ( addr len -- ) \ text to be "typed" into front QE window
- \ if no window open in QE, no action from QE, just a beep
- \ put: QEstr \ 27Jan94 DBH
- \ 'type TEXT send: self ;m
- add: QEstr ;m
-
- variable emitvar 4 allot
-
- :m cr: ( -- oserr )
- 13 emitvar c!
- emitvar 1 text: self
- 'type TEXT send: self
- clear: QEstr ;m
-
- :m newWindow: ( addr len -- oserr ) \ opens a new window in QE, does not create a file on disk
- \ if no more available windows in QE, no action, just a beep
- put: QEstr
- 'type NEWF send: self ;m
-
- :m putRect: ( l t r b -- oserr ) \ will set the front QE window portrect to these values
- \ if no window open in QE, no action from QE, just a beep
- put: temprect
- addr: temprect 8 put: QEstr
- 'type RECT send: self ;m
-
- :m find: ( addr len -- oserr ) \ will request that QE find first occurrence of
- \ the given text in the front qe window. We are limited to strings of length
- \ 255 and less. All searches will be case insensitive.
- put: QEstr
- >uc: QEstr \ QE needs all upper case for this
- 'type FIND send: self ;m
-
- ;class
-
- QE tQE \ we now have just one object for sending commands to Quick Edit
-
-
- : inittQE
- instld? ?EXIT \ Mustn't do this in installed apps
- AppleEvents? 0EXIT
- new: tQE ;
-
- inittQE
-
- ' inittQE add: init_actions
-
- endload
-
- +echo
-
- file testfile
-
- : GO1
- 'type TEXT 1 stdget: testfile . cr
- testfile 10 20 openFile: tQE . ;
-
- : GO2
- " Hello World" text: tQE cr: tQE . ; \ note how we must always end with a cr: to send:
-
- : GO3
- " My File Name" newwindow: tQE . ;
-
- : GO4
- 100 50 300 350 putrect: tQE . ;
-
- endload
-
- ****** GENERAL COMMENTS *******
-
-
- It is very important to understand the "trick" being used here for communication between Mops and
- QE. We follow Apple's recipe for everything except for the descriptor record scheme. Instead of
- building and then deciphering the seemingly overly complex descriptor records for each AE, it seemed
- to me to be much more straightforward to just send a handle to whatever data structure we wish.
- Since we control everything at both ends (Mops and QE), then why go through all of the gyrations of
- the AEdesc record handling? We avoid having to deal with any of the AEPutParam/AEGetParam etc.
- Also, we don't even have to deal with AEInstallEventHandler or AEProcessAppleEvent!
-
- What we do is to only define our AppleEvents by class and not by also providing an ID. This does
- not seem to be much of a limitation on defining AEs since there are certainly plenty of different
- classes we could define with the 32 bit class identifier. Most importantly, we have now freed up
- the ID of our AE for use in any way that we wish, and we wish to make our ID the handle to the data
- we want to pass from Mops to QE or vice versa. I don't know what kind of problems this could cause.
- To date, I have noticed no problems. But this does not seem to be the way Apple intended. So
- beware. Note that both Mops and QE accomplish AE communication in exactly the same (non-standard)
- way.
-
- The memory problem that both QE 2.4 and the original Mops 2.4 release suffered was not related
- to this scheme. That problem existed due to the lack of understanding on my part of the need for
- disposing AppleEvents and AE Replies after each AESend. But note that we do not need to create
- and dispose our descriptor record itself. But we must use AEDisposeDesc to dispose of the
- AppleEvent and AEReply ( no AEDisposeAppleEvent exists, apparently).
-
- -Doug Hoffman \ 12Feb94